﻿//IQFeedMessage.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo.History.IQFeed
{
	using System;

	using Ecng.Common;

	internal enum IQFeedMessageType
	{
		Error,
		System,
		Time,
		End,
		Data,
		ListedMarket,
		Security,
		HistoryTrade,
		Quote,
		Trade,
	}

	internal enum IQFeedSearchField
	{
		Symbol, 
		Description
	}

	internal enum IQFeedFilterType
	{
		Market,
		SecurityType
	}

	internal abstract class IQFeedMessage
	{
		protected IQFeedMessage(IQFeedMessageType type, string value)
		{
			Type = type;
			Value = value;
		}

		public IQFeedMessageType Type { get; set; }
		public string Value { get; set; }

		public override string ToString()
		{
			return "{0}: {1}".Put(this.Type, this.Value);
		}
	}

	internal class IQFeedTimeMessage : IQFeedMessage
	{
		public IQFeedTimeMessage(string value)
			: base(IQFeedMessageType.Time, value)
		{
			Time = value.ToDateTime("yyyyMMdd HH:mm:ss");
		}

		public DateTime Time { get; private set; }
	}

	internal class IQFeedListedMarketMessage : IQFeedMessage
	{
		public IQFeedListedMarketMessage(string value)
			: base(IQFeedMessageType.Data, value)
		{
			var parts = value.CommaSplit();

			Id = parts[0].To<int>();
			Code = parts[1];
			Name = parts[2];
		}

		public int Id { get; private set; }
		public string Code { get; private set; }
		public string Name { get; private set; }
	}

	internal class IQFeedSecurityMessage : IQFeedMessage
	{
		public IQFeedSecurityMessage(string value)
			: base(IQFeedMessageType.Data, value)
		{
			var parts = value.CommaSplit();

			Code = parts[0];
			Market = parts[1].To<int>();
			SecurityType = parts[2].To<int>();
			Name = parts[3];
		}

		public string Code { get; private set; }
		public string Name { get; private set; }
		public int Market { get; private set; }
		public int SecurityType { get; private set; }
	}

	internal class IQFeedHistoryTradeMessage : IQFeedMessage
	{
		public IQFeedHistoryTradeMessage(string value)
			: base(IQFeedMessageType.HistoryTrade, value)
		{
			var parts = value.CommaSplit();

			Id = parts[6].To<int>();
			Time = parts[0].ToDateTime("yyyy-MM-dd HH:mm:ss.fff");
			Price = parts[1].To<decimal>();
			Volume = parts[2].To<decimal>();
		}

		public int Id { get; private set; }
		public DateTime Time { get; private set; }
		public decimal Price { get; private set; }
		public decimal Volume { get; private set; }
	}

	internal class IQFeedQuoteMessage : IQFeedMessage
	{
		public IQFeedQuoteMessage(string value)
			: base(IQFeedMessageType.Quote, value)
		{
			var parts = value.CommaSplit();

			Symbol = parts[0];
			MarketMaker = parts[1];
			Bid = parts[2].To<decimal>();
			Ask = parts[3].To<decimal>();
			BidVolume = parts[4].To<decimal>();
			AskVolume = parts[5].To<decimal>();
			Date = parts[7].ToDateTime("yyyy-MM-dd");
			BidTime = Date.Add(parts[6].To<TimeSpan>());
			AskTime = Date.Add(parts[9].To<TimeSpan>());
			IsBidValid = parts[10] == "T";
			IsAskValid = parts[11] == "T";
		}

		public string Symbol { get; set; }
		public string MarketMaker { get; set; }
		
		public decimal Bid { get; private set; }
		public decimal BidVolume { get; private set; }
		public DateTime BidTime { get; private set; }
		public bool IsBidValid { get; set; }

		public decimal Ask { get; private set; }
		public decimal AskVolume { get; private set; }
		public DateTime AskTime { get; private set; }
		public bool IsAskValid { get; set; }

		public DateTime Date { get; private set; }

		//public byte UpdateCondition { get; set; }
	}

	internal class IQFeedTradeMessage : IQFeedMessage
	{
		public IQFeedTradeMessage(string value)
			: base(IQFeedMessageType.Trade, value)
		{
			var parts = value.CommaSplit();

			//Symbol,TickID,Last Trade Date,Most Recent Trade TimeMS,Most Recent Trade,Most Recent Trade Size,Message Contents
			if (!parts[6].Contains("C"))
				throw new InvalidOperationException("Набор данных '{0}' не содержит информацию о сделке.".Put(value));

			Symbol = parts[0];
			Id = parts[1].To<int>();
			Time = parts[2].ToDateTime("MM/dd/yyyy").Add(parts[3].To<TimeSpan>());
			Price = parts[4].To<decimal>();
			Volume = parts[5].To<decimal>();
		}

		public int Id { get; private set; }
		public string Symbol { get; set; }
		public DateTime Time { get; private set; }
		public decimal Price { get; private set; }
		public decimal Volume { get; private set; }
	}

	internal class IQFeedUserMessage : IQFeedMessage
	{
		public IQFeedUserMessage(string value)
			: base(IQFeedMessageType.Data, value)
		{
		}
	}
}